﻿#include "OiPCH.hpp"
#include "Tools/OiPlyTool.hpp"

namespace Oi
{
    namespace PLScannerCore
    {
        class DefinitionPointDlg : public QDialog
        {
        public:
            DefinitionPointDlg(const DefinitionType mtype, QWidget* parent);

            void setPoint(const DefinitionPoint& mp);

            void point(DefinitionPoint& mp);

        public:
            DefinitionType type;
            QLineEdit* xValue;
            QLineEdit* ylValue;
            QLineEdit* y2Value;
            QComboBox* additionType;
            QDialogButtonBox* buttons;
        };

        class DefinitionEditDlgImpl : public Impl<DefinitionEditDlg>
        {
        public:
            void init(const DefinitionType type);

        public:
            void updateProfile();
            void updateTable();

        public:
            ProfileView* _view;
            QTableWidget* _table;
            QLineEdit* _width;
            QLineEdit* _thickness;
            QPushButton* _insert;
            QPushButton* _remove;
            QPushButton* _edit;

        public:
            DefinitionPointDlg* _dlg;

        public:
            ProductParams _params;

        public:
            DefinitionType _type;
        };

        DefinitionPointDlg::DefinitionPointDlg(const DefinitionType mtype, QWidget* parent) : QDialog(parent)
        {
            setWindowTitle("控制点编辑");

            QVBoxLayout* layout = new QVBoxLayout(this);
            QFormLayout* editLayout = new QFormLayout();

            type = mtype;

            xValue = new QLineEdit(this);
            ylValue = new QLineEdit(this);
            y2Value = new QLineEdit(this);
            additionType = new QComboBox(this);
            additionType->addItems({ "连续点","突变点" });

            auto validator = new QDoubleValidator();
            validator->setRange(0.1, 999.0, 2);
            xValue->setValidator(validator);

            validator = new QDoubleValidator();
            validator->setRange(0.1, 99.9, 2);
            ylValue->setValidator(validator);
            y2Value->setValidator(validator);

            editLayout->addRow("位置", xValue);
            editLayout->addRow("左侧厚度", ylValue);
            editLayout->addRow("右侧厚度", y2Value);
            editLayout->addRow("类型", additionType);


            if (type & DT_HalfWidth)
            {
                y2Value->setEnabled(false);
            }

            buttons = new QDialogButtonBox(QDialogButtonBox::Cancel | QDialogButtonBox::Ok, this);

            layout->addLayout(editLayout);
            layout->addWidget(buttons);
        }

        void DefinitionPointDlg::setPoint(const DefinitionPoint& mp)
        {
            xValue->setText(QString::number(mp.distance));
            ylValue->setText(QString::number(fabs(mp.thicknessLeft)));
            y2Value->setText(QString::number(fabs(mp.thicknessRight)));
            additionType->setCurrentIndex((mp.type & DT_Mutational) ? 1 : 0);

            update();
        }

        void DefinitionPointDlg::point(DefinitionPoint& mp)
        {
            mp.distance = xValue->text().toDouble();
            mp.thicknessLeft = ylValue->text().toDouble();
            mp.thicknessRight = y2Value->text().toDouble();
            mp.type = type + (additionType->currentIndex() == 0 ? 0 : DT_Mutational);
           // mp.radius = rValue->text().toDouble();
        }

        void DefinitionEditDlgImpl::init(const DefinitionType type)
        {
            OI_Q(DefinitionEditDlg);

            if (type == DT_FullWidth)
            {
                q->setWindowTitle(DefinitionEditDlg::tr("对称/非对称全宽-模板编辑器"));
            }
            else if (type == DT_HalfWidth)
            {
                q->setWindowTitle(DefinitionEditDlg::tr("对称半宽-模板编辑器"));
            }

            _type = type;

            QHBoxLayout* mainLayout = new QHBoxLayout(q);
            _view = new ProfileView();

            QVBoxLayout* cLayout = new QVBoxLayout();
            QFormLayout* ctLayout = new QFormLayout();

            _width = new QLineEdit();
            _thickness = new QLineEdit();
            _width->setValidator(new QDoubleValidator());
            _thickness->setValidator(new QDoubleValidator());

            ctLayout->addRow("宽度", _width);
            ctLayout->addRow("边缘厚度", _thickness);

            _table = new QTableWidget();

            _table->setSelectionBehavior(QAbstractItemView::SelectRows);
            _table->setSelectionMode(QAbstractItemView::SingleSelection);
            _table->setEditTriggers(QAbstractItemView::NoEditTriggers);
            _table->setColumnCount(4);

            QStringList titleList;

            titleList << DefinitionEditDlg::tr("位置") << DefinitionEditDlg::tr("左厚度") << DefinitionEditDlg::tr("右厚度") << DefinitionEditDlg::tr("类型");
            _table->setHorizontalHeaderLabels(titleList);
            _table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);

            cLayout->addLayout(ctLayout);
            cLayout->addWidget(_table);

            QVBoxLayout* rLayout = new QVBoxLayout();
           
            _insert = new QPushButton(DefinitionEditDlg::tr("插入"));
            _remove = new QPushButton(DefinitionEditDlg::tr("删除"));
            _edit = new QPushButton(DefinitionEditDlg::tr("修改"));

            rLayout->addWidget(_insert, 1);
            rLayout->addWidget(_remove, 1);
            rLayout->addWidget(_edit, 1);
            rLayout->addStretch(2);

            mainLayout->addWidget(_view, 4);
            mainLayout->addLayout(cLayout, 2);
            mainLayout->addLayout(rLayout, 1);

            _dlg = new DefinitionPointDlg(_type, q);
            _dlg->resize(600, 500);

            q->connect(_width, &QLineEdit::editingFinished, q, &DefinitionEditDlg::onUpdateProfile);
            q->connect(_thickness, &QLineEdit::editingFinished, q, &DefinitionEditDlg::onUpdateProfile);
            q->connect(_insert, &QPushButton::clicked, q, &DefinitionEditDlg::onInsert);
            q->connect(_remove, &QPushButton::clicked, q, &DefinitionEditDlg::onRemove);
            q->connect(_edit, &QPushButton::clicked, q, &DefinitionEditDlg::onEdit);

            q->connect(_dlg->buttons, &QDialogButtonBox::accepted, q, &DefinitionEditDlg::onEditCompleted);
            q->connect(_dlg->buttons, &QDialogButtonBox::rejected, _dlg, &QDialog::reject);

            updateTable();
        }

        void DefinitionEditDlgImpl::updateProfile()
        {
            _params.materialsWidth = _width->text().toDouble();
            _params.materialsThickness = _thickness->text().toDouble();


            _params.profiles = ProductParams::createProfile(
                _params.materialsWidth,
                _params.materialsThickness,
                _params.definitionPoints);

            _view->chart()->updateProfiles(_params.profiles);

            _view->chart()->autoRange();
        }

        void DefinitionEditDlgImpl::updateTable()
        {
            _table->clearContents();

            _table->setRowCount(_params.definitionPoints.count());

            _table->blockSignals(true);

            int row = 0;

            for(auto& om : _params.definitionPoints)
            {
                QTableWidgetItem* dateItem = new QTableWidgetItem();
                dateItem->setTextAlignment(Qt::AlignCenter);
                dateItem->setText(QString::number(om.distance));
                _table->setItem(row, 0, dateItem);

                dateItem = new QTableWidgetItem();
                dateItem->setTextAlignment(Qt::AlignCenter);
                dateItem->setText(QString::number(om.thicknessLeft));
                _table->setItem(row, 1, dateItem);

                dateItem = new QTableWidgetItem();
                dateItem->setTextAlignment(Qt::AlignCenter);
                dateItem->setText(QString::number(om.thicknessRight));
                _table->setItem(row, 2, dateItem);

                dateItem = new QTableWidgetItem();
                dateItem->setTextAlignment(Qt::AlignCenter);
                dateItem->setText((om.type & DT_Mutational) ? DefinitionEditDlg::tr("突变点"):DefinitionEditDlg::tr("连续点"));
                _table->setItem(row, 3, dateItem);

                row++;
            }

            _table->blockSignals(false);
        }

        DefinitionEditDlg::DefinitionEditDlg(const DefinitionType type, QWidget * parent)
            : QDialog(parent)
        {
            OI_I(DefinitionEditDlg)->init(type);
        }

        void DefinitionEditDlg::setParams(const ProductParams params)
        {
            OI_F(DefinitionEditDlg);
            d->_params = params;

            d->_width->blockSignals(true);
            d->_thickness->blockSignals(true);

            d->_width->setText(QString::number(params.materialsWidth));
            d->_thickness->setText(QString::number(params.materialsThickness));

            d->_width->blockSignals(false);
            d->_thickness->blockSignals(false);

            d->updateProfile();
            d->updateTable();
        }

        ProductParams DefinitionEditDlg::params() const
        {
            return OI_IMPL()->_params;
        }

        void DefinitionEditDlg::closeEvent(QCloseEvent * evt)
        {
            OI_F(DefinitionEditDlg);
        }

        void DefinitionEditDlg::onUpdateProfile()
        {
            OI_IMPL()->updateProfile();
        }

        void DefinitionEditDlg::onInsert()
        {
            OI_F(DefinitionEditDlg);

            DefinitionPoint point;

            d->_dlg->setPoint(point);

            if (d->_dlg->exec() == QDialog::Accepted)
            {
                d->_dlg->point(point);

                d->_params.definitionPoints.append(point);
                d->_params.insParams[TT_DefinitionTool + d->_params.definitionPoints.size() - 1] = QVariant::fromValue(PlyTool::toolDefaultValues(TT_DefinitionTool));

                d->updateProfile();
                d->updateTable();
            }
        }

        void DefinitionEditDlg::onRemove()
        {
            OI_F(DefinitionEditDlg);

            int row = d->_table->currentRow();

            d->_params.definitionPoints.removeAt(row);

            QList<QVariant> insParams;

            for (auto iter = d->_params.insParams.begin(); iter != d->_params.insParams.end(); )
            {
                if (iter.key() >= TT_DefinitionTool && iter.key() < TT_MeasureThicknessTool)
                {
                    if (iter.key() != row)
                    {
                        insParams.push_back(iter.value());
                    }

                    iter = d->_params.insParams.erase(iter);
                }
                else
                {
                    iter++;
                }
            }

            for (int i = 0; i < insParams.size() ; i++)
            {
                d->_params.insParams[TT_DefinitionTool + i] = insParams[i];
            }

            d->updateProfile();
            d->updateTable();
        }

        void DefinitionEditDlg::onEdit()
        {
            OI_F(DefinitionEditDlg);

            int row = d->_table->currentRow();

            if(row >= 0)
            {
                if (d->_params.definitionPoints[row].type & d->_type)
                {
                    d->_dlg->setPoint(d->_params.definitionPoints[row]);

                    if (d->_dlg->exec() == QDialog::Accepted)
                    {
                        d->_dlg->point(d->_params.definitionPoints[row]);
                        d->updateProfile();
                        d->updateTable();
                    }
                }
                else
                {
                    OiAlerter() << DefinitionEditDlg::tr("控制点类型不一致，无法修改");
                }
            }
        }

        void DefinitionEditDlg::onEditCompleted()
        {
            OI_F(DefinitionEditDlg);
         
            d->_dlg->accept();
        }
      
    }
}